package hservice

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"advertoper/db"
	"advertoper/errorcode"
	"advertoper/rpc/client/zjservice"

	"doubimeizhi.com/datatable"
	"doubimeizhi.com/utility"

	log "github.com/cihub/seelog"
)

var (
	defaultZJSeckillInfoService *ZJSeckillInfoService
)

type ZJSeckillInfoService struct {
	zjSeckillInfo          map[int]*ZJSeckillItem
	zjSeckillLock          *sync.RWMutex
	zjSeckillSellNumUpLock *sync.RWMutex //秒杀商品销售数目上报的锁
	zjSeckillMaxId         int
}

func newZJSeckillInfoService() *ZJSeckillInfoService {
	service := &ZJSeckillInfoService{}
	service.zjSeckillInfo = make(map[int]*ZJSeckillItem)
	service.zjSeckillLock = new(sync.RWMutex)
	service.zjSeckillSellNumUpLock = new(sync.RWMutex)
	service.zjSeckillMaxId = 0
	service.loadDataInit()
	go service.loopSeckillMemory() //位置zjseckill_user_service.go
	return service
}

func GetZJSeckillInfoService() *ZJSeckillInfoService {
	if defaultZJSeckillInfoService == nil {
		defaultZJSeckillInfoService = newZJSeckillInfoService()
	}
	return defaultZJSeckillInfoService
}

type ZJSeckillAdmin struct {
	SeckillProductType string `json:"seckill_product_type"` //秒杀产品类型，zjservice:服务,zjmall:商城
	SeckillProductId   int    `json:"seckill_product_id"`   //秒杀的产品唯一标识，如服务的service_id,商城的goods_id
	SeckillProductSid  int64  `json:"seckill_product_sid"`  //秒杀的产品二级标识，如服务中的挂式空调
	ClickAble          int    `json:"clickable"`
	Title              string `json:"title"`
	PicUrl             string `json:"pic_url"`
	BackgroundPicture  string `json:"background_picture"`
	BackgroundColor    string `json:"background_color"`
	Routers            string `json:"routers"`
	BuyRouters         string `json:"buy_routers"`    //下单路由
	OriginalPrice      int    `json:"original_price"` //原价
	Price              int    `json:"price"`
	Unit               string `json:"unit"` //单位
	SellNumber         int    `json:"sell_number"`
	TotalNumber        int    `json:"total_number"`
	ShareUrl           string `json:"share_url"`
	ShareLogo          string `json:"share_logo"`
	ShareTitle         string `json:"share_title"`
	ShareContent       string `json:"share_content"`
}

//添加
type ZJSeckillAddReq struct {
	PublicAdd
	ZJSeckillAdmin
	SeckillStart int64 `json:"seckill_start"` //秒杀开始时间
	SeckillEnd   int64 `json:"seckill_end"`   //秒杀结束时间
}

//修改
type ZJSeckillUpdateReq struct {
	PublicUpdate
	ZJSeckillAddReq
	SeckillStart int64 `json:"seckill_start"` //秒杀开始时间
	SeckillEnd   int64 `json:"seckill_end"`   //秒杀结束时间
}

//缓存
type ZJSeckillItem struct {
	PublicItme
	ZJSeckillUpdateReq
	SeckillStart int64 `json:"seckill_start"` //秒杀开始时间
	SeckillEnd   int64 `json:"seckill_end"`   //秒杀结束时间
}

//web显示列表
type ZJSeckillList struct {
	PublicList
	ZJSeckillAdmin
	SeckillStart string `json:"seckill_start"` //秒杀开始时间
	SeckillEnd   string `json:"seckill_end"`   //秒杀结束时间
}

//客户端返回列表（加上元素id）
type ZJSeckillUserList struct {
	Id int `json:"id"`
	UserZJSeckillItem
}

//印证秒杀项目数据
type VerifySeckillResp struct {
	// IsSeckill        int   `json:"is_seckill"`     //是否是秒杀产品，0:不是,1:是
	SeckillProductSid int64 `json:"activity_product_sdid"`
	Price             int   `json:"activity_price"` //秒杀价格
	OriginalPrice     int   `json:"original_price"` //秒杀原价
	SeckillStartTick  int64 `json:"activity_start_tick"`
	SeckillEndTick    int64 `json:"activity_end_tick"`
	TotalNum          int   `json:"total_number"`
	SellNum           int   `json:"sell_number"`
}

//load数据
func (p *ZJSeckillInfoService) loadDataInit() {
	daq := datatable.NewDataTableQuery()
	daq.SetTableName("zjseckill")
	daq.PushField(&datatable.FiledItem{Alias: "id", Field: "id"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_product_type", Field: "seckill_product_type"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_product_id", Field: "seckill_product_id"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_product_sid", Field: "seckill_product_sid"})
	daq.PushField(&datatable.FiledItem{Alias: "region_code", Field: "region_code"})
	daq.PushField(&datatable.FiledItem{Alias: "clickable", Field: "clickable"})
	daq.PushField(&datatable.FiledItem{Alias: "title", Field: "title"})
	daq.PushField(&datatable.FiledItem{Alias: "price", Field: "price"})
	daq.PushField(&datatable.FiledItem{Alias: "original_price", Field: "original_price"})
	daq.PushField(&datatable.FiledItem{Alias: "sell_number", Field: "sell_number"})
	daq.PushField(&datatable.FiledItem{Alias: "total_number", Field: "total_number"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_start", Field: "seckill_start"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_end", Field: "seckill_end"})
	daq.PushField(&datatable.FiledItem{Alias: "share_url", Field: "share_url"})
	daq.PushField(&datatable.FiledItem{Alias: "share_logo", Field: "share_logo"})
	daq.PushField(&datatable.FiledItem{Alias: "share_title", Field: "share_title"})
	daq.PushField(&datatable.FiledItem{Alias: "share_content", Field: "share_content"})
	daq.PushField(&datatable.FiledItem{Alias: "pic_url", Field: "pic_url"})
	daq.PushField(&datatable.FiledItem{Alias: "routers", Field: "routers"})
	daq.PushField(&datatable.FiledItem{Alias: "buy_routers", Field: "buy_routers"})
	daq.PushField(&datatable.FiledItem{Alias: "background_picture", Field: "background_picture"})
	daq.PushField(&datatable.FiledItem{Alias: "background_color", Field: "background_color"})
	daq.PushField(&datatable.FiledItem{Alias: "starttick", Field: "starttick"})
	daq.PushField(&datatable.FiledItem{Alias: "endtick", Field: "endtick"})
	daq.PushField(&datatable.FiledItem{Alias: "insert_tick", Field: "insert_tick", OrderBy: datatable.DESC})
	daq.PushField(&datatable.FiledItem{Alias: "update_tick", Field: "update_tick"})
	daq.PushField(&datatable.FiledItem{Alias: "status", Field: "status"})
	sql, values := daq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	results, err := mysqlHelper.Query(sql, values...)
	if err != nil {
		log.Errorf("load zjseckill list fail ,~~~loadDataInit,err is %s", err.Error())
		return
	}
	p.zjSeckillLock.Lock()
	defer p.zjSeckillLock.Unlock()
	for _, dt := range results {
		item := &ZJSeckillItem{}
		item.Id = mysqlHelper.GetColInt(dt, "id")
		item.SeckillProductType = mysqlHelper.GetColString(dt, "seckill_product_type")
		item.SeckillProductId = mysqlHelper.GetColInt(dt, "seckill_product_id")
		item.SeckillProductSid = mysqlHelper.GetColInt64(dt, "seckill_product_sid")
		item.RegionCode = mysqlHelper.GetColString(dt, "region_code")
		item.ClickAble = mysqlHelper.GetColInt(dt, "clickable")
		item.PicUrl = mysqlHelper.GetColString(dt, "pic_url")
		item.Title = mysqlHelper.GetColString(dt, "title")
		item.Price = mysqlHelper.GetColInt(dt, "price")
		item.OriginalPrice = mysqlHelper.GetColInt(dt, "original_price")
		item.SellNumber = mysqlHelper.GetColInt(dt, "sell_number")
		item.TotalNumber = mysqlHelper.GetColInt(dt, "total_number")
		item.SeckillStart = mysqlHelper.GetColInt64(dt, "seckill_start")
		item.SeckillEnd = mysqlHelper.GetColInt64(dt, "seckill_end")
		item.ShareUrl = mysqlHelper.GetColString(dt, "share_url")
		item.ShareLogo = mysqlHelper.GetColString(dt, "share_logo")
		item.ShareTitle = mysqlHelper.GetColString(dt, "share_title")
		item.ShareContent = mysqlHelper.GetColString(dt, "share_content")
		item.Routers = mysqlHelper.GetColString(dt, "routers")
		item.BuyRouters = mysqlHelper.GetColString(dt, "buy_routers")
		item.BackgroundPicture = mysqlHelper.GetColString(dt, "background_picture")
		item.BackgroundColor = mysqlHelper.GetColString(dt, "background_color")
		item.StartTick = mysqlHelper.GetColInt64(dt, "starttick")
		item.EndTick = mysqlHelper.GetColInt64(dt, "endtick")
		item.InsertTick = mysqlHelper.GetColInt64(dt, "insert_tick")
		item.UpdateTick = mysqlHelper.GetColInt64(dt, "update_tick")
		item.Status = mysqlHelper.GetColInt(dt, "status")

		if item.Id > p.zjSeckillMaxId {
			p.zjSeckillMaxId = item.Id
		}
		//加入缓存
		p.zjSeckillInfo[item.Id] = item
	}
	log.Infof("load zjseckill data,len is :%d", len(p.zjSeckillInfo))
}

//添加
func (p *ZJSeckillInfoService) ZJSeckillAdd(req *ZJSeckillAddReq) (uint, string) {
	if req.EndTick < req.StartTick {
		return 1002, "失效时间不能小于开始有效时间"
	}

	regionCode := strings.Split(req.RegionCode, ",")
	if len(regionCode) == 1 {
		if len(regionCode[0]) < 4 {
			if regionCode[0] != "all" {
				return 20001, "区域不合法"
			}
		}
	}
	if len(regionCode) > 1 {
		for _, re := range regionCode {
			if len(re) < 4 {
				log.Warnf("区域不合法,re: %s", re)
				return 20001, "区域不合法"
			}
		}
	}

	p.zjSeckillLock.Lock()
	defer p.zjSeckillLock.Unlock()
	//保存
	nowTime := time.Now().Unix()
	//生效时间不能小于当前时间
	if req.StartTick <= nowTime {
		return 1003, "生效时间不能小于当前时间"
	}
	if req.SeckillStart <= req.StartTick {
		return 1005, "秒杀开始时间不能小于上架时间"
	}
	if req.SeckillEnd >= req.EndTick {
		return 1006, "秒杀结束不能大于上架时间"
	}

	//判断统一service_id下秒杀时间必须一致
	for _, v := range p.zjSeckillInfo {
		if v.SeckillProductId == req.SeckillProductId {
			if v.EndTick < nowTime || v.Status == -1 {
				continue
			} else {
				if v.SeckillStart != req.SeckillStart || v.SeckillEnd != req.SeckillEnd {
					return 1004, "该一级产品有秒杀，请确保秒杀时间一致"
				}
			}
		}
	}

	p.zjSeckillMaxId += 1

	data := make(map[string]*utility.MySQLFieldValue)
	data["id"] = utility.NewMySQLFieldValue(p.zjSeckillMaxId, false)
	data["seckill_product_type"] = utility.NewMySQLFieldValue(req.SeckillProductType, false)
	data["seckill_product_id"] = utility.NewMySQLFieldValue(req.SeckillProductId, false)
	data["seckill_product_sid"] = utility.NewMySQLFieldValue(req.SeckillProductSid, false)
	data["region_code"] = utility.NewMySQLFieldValue(req.RegionCode, false)
	data["clickable"] = utility.NewMySQLFieldValue(req.ClickAble, false)
	data["pic_url"] = utility.NewMySQLFieldValue(req.PicUrl, false)
	data["title"] = utility.NewMySQLFieldValue(req.Title, false)
	data["price"] = utility.NewMySQLFieldValue(req.Price, false)
	data["original_price"] = utility.NewMySQLFieldValue(req.OriginalPrice, false)
	data["sell_number"] = utility.NewMySQLFieldValue(req.SellNumber, false)
	data["total_number"] = utility.NewMySQLFieldValue(req.TotalNumber, false)
	data["seckill_start"] = utility.NewMySQLFieldValue(req.SeckillStart, false)
	data["seckill_end"] = utility.NewMySQLFieldValue(req.SeckillEnd, false)
	data["share_url"] = utility.NewMySQLFieldValue(req.ShareUrl, false)
	data["share_logo"] = utility.NewMySQLFieldValue(req.ShareLogo, false)
	data["share_title"] = utility.NewMySQLFieldValue(req.ShareTitle, false)
	data["share_content"] = utility.NewMySQLFieldValue(req.ShareContent, false)
	data["background_picture"] = utility.NewMySQLFieldValue(req.BackgroundPicture, false)
	data["background_color"] = utility.NewMySQLFieldValue(req.BackgroundColor, false)
	data["routers"] = utility.NewMySQLFieldValue(req.Routers, false)
	data["buy_routers"] = utility.NewMySQLFieldValue(req.BuyRouters, false)
	data["starttick"] = utility.NewMySQLFieldValue(req.StartTick, false)
	data["endtick"] = utility.NewMySQLFieldValue(req.EndTick, false)
	data["insert_tick"] = utility.NewMySQLFieldValue(nowTime, false)
	data["update_tick"] = utility.NewMySQLFieldValue(nowTime, false)
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	_, err := mysqlHelper.SaveRecord(data, "zjseckill")
	if err != nil {
		log.Errorf("insert zjseckill fail ,~~~zjseckillAdd,err is %s", err.Error())
		return errorcode.EC_GL_INTERNAL_ERROR, errorcode.Msg(errorcode.EC_GL_INTERNAL_ERROR)
	}
	//添加缓存
	item := &ZJSeckillItem{}
	item.Id = p.zjSeckillMaxId
	item.SeckillProductType = req.SeckillProductType
	item.SeckillProductId = req.SeckillProductId
	item.SeckillProductSid = req.SeckillProductSid
	item.RegionCode = req.RegionCode
	item.ClickAble = req.ClickAble
	item.PicUrl = req.PicUrl
	item.Title = req.Title
	item.Price = req.Price
	item.OriginalPrice = req.OriginalPrice
	item.SellNumber = req.SellNumber
	item.TotalNumber = req.TotalNumber
	item.SeckillStart = req.SeckillStart
	item.SeckillEnd = req.SeckillEnd
	item.ShareUrl = req.ShareUrl
	item.ShareContent = req.ShareContent
	item.ShareLogo = req.ShareLogo
	item.ShareTitle = req.ShareTitle
	item.BackgroundPicture = req.BackgroundPicture
	item.BackgroundColor = req.BackgroundColor
	item.Routers = req.Routers
	item.BuyRouters = req.BuyRouters
	item.StartTick = req.StartTick
	item.EndTick = req.EndTick
	item.InsertTick = nowTime
	item.UpdateTick = nowTime
	item.Status = 1

	p.zjSeckillInfo[p.zjSeckillMaxId] = item

	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS)
}

//修改
func (p *ZJSeckillInfoService) ZJSeckillUpdate(req *ZJSeckillUpdateReq) (uint, string) {
	//获取缓存数据
	oldData, ok := p.zjSeckillInfo[req.Id]
	if !ok {
		return 101, "row is not invalid"
	}
	nowTime := time.Now().Unix()
	if req.Status == -1 && nowTime > oldData.SeckillEnd {
		//跳过印证
	} else {
		//生效时间不能小于当前时间
		if req.StartTick <= nowTime {
			return 1003, "生效时间不能小于当前时间"
		}
		//秒杀开始时间要大于当前时间10分钟
		if req.SeckillStart <= nowTime+10*60 {
			return 1007, "秒杀开始时间要大于当前时间10分钟"
		}
		if req.SeckillStart <= req.StartTick {
			return 1005, "秒杀开始时间不能小于上架时间"
		}
		if req.SeckillEnd >= req.EndTick {
			return 1006, "秒杀结束不能大于上架时间"
		}
		//判断统一service_id下秒杀时间必须一致
		if req.Status == 1 { //当编辑的秒杀项目是有效的才判断
			for k, v := range p.zjSeckillInfo {
				if v.Status == 1 { //只判断缓存中有效的
					if v.SeckillProductId == req.SeckillProductId {
						if k != req.Id { //当service_id相等，排除掉自身
							if v.SeckillStart != req.SeckillStart || v.SeckillEnd != req.SeckillEnd {
								return 1004, "该一级产品有秒杀，请确保秒杀时间一致"
							}
						}
					}
				}
			}
		}
	}

	currDate := &ZJSeckillItem{}
	//将老的数据copy一份
	currDate.Id = oldData.Id
	currDate.SeckillProductType = oldData.SeckillProductType
	currDate.SeckillProductId = oldData.SeckillProductId
	currDate.SeckillProductSid = oldData.SeckillProductSid
	currDate.EndTick = oldData.EndTick
	currDate.InsertTick = oldData.InsertTick
	currDate.BackgroundPicture = oldData.BackgroundPicture
	currDate.BackgroundColor = oldData.BackgroundColor
	currDate.RegionCode = oldData.RegionCode
	currDate.Routers = oldData.Routers
	currDate.BuyRouters = oldData.BuyRouters
	currDate.StartTick = oldData.StartTick
	currDate.Status = oldData.Status
	currDate.PicUrl = oldData.PicUrl
	currDate.Title = oldData.Title
	currDate.Price = oldData.Price
	currDate.OriginalPrice = oldData.OriginalPrice
	currDate.SellNumber = oldData.SellNumber
	currDate.TotalNumber = oldData.TotalNumber
	currDate.SeckillStart = oldData.SeckillStart
	currDate.SeckillEnd = oldData.SeckillEnd
	currDate.ShareUrl = oldData.ShareUrl
	currDate.ShareContent = oldData.ShareContent
	currDate.ShareLogo = oldData.ShareLogo
	currDate.ShareTitle = oldData.ShareTitle
	currDate.UpdateTick = oldData.UpdateTick
	currDate.ClickAble = oldData.ClickAble

	updaq := datatable.NewDataTableUpdate()
	updaq.SetTableName("zjseckill")
	//说明，当int类型的参数不带的时候会解析到0，而需要将int类型的update为0，则传-101
	//同理，string类型的传"null"

	if req.SeckillProductType != "" {
		updaq.SetUpdateValue("seckill_product_type=?", req.SeckillProductType)
		currDate.SeckillProductType = req.SeckillProductType
	}
	if req.SeckillProductId != 0 {
		updaq.SetUpdateValue("seckill_product_id=?", req.SeckillProductId)
		currDate.SeckillProductId = req.SeckillProductId
	}
	if req.SeckillProductSid != 0 {
		if req.SeckillProductSid == -101 {
			req.SeckillProductSid = 0
		}
		updaq.SetUpdateValue("seckill_product_sid=?", req.SeckillProductSid)
		currDate.SeckillProductSid = req.SeckillProductSid
	}
	if req.RegionCode != "" {
		updaq.SetUpdateValue("region_code=?", req.RegionCode)
		currDate.RegionCode = req.RegionCode
	}
	if req.ClickAble != 0 {
		updaq.SetUpdateValue("clickable=?", req.ClickAble)
		currDate.ClickAble = req.ClickAble
	}
	if req.PicUrl != "" {
		updaq.SetUpdateValue("pic_url=?", req.PicUrl)
		currDate.PicUrl = req.PicUrl
	}
	if req.Price != 0 {
		if req.Price == -101 { //价格就是需要为0，那么-101代表0
			req.Price = 0
		}
		updaq.SetUpdateValue("price=?", req.Price)
		currDate.Price = req.Price
	}
	if req.OriginalPrice != 0 {
		updaq.SetUpdateValue("original_price=?", req.OriginalPrice)
		currDate.OriginalPrice = req.OriginalPrice
	}
	if req.TotalNumber != 0 {
		if req.TotalNumber == -101 {
			req.TotalNumber = 0
		}
		if req.TotalNumber < currDate.SellNumber {
			//异常
			return 2001, "总数不能小于已售数目"
		}
		updaq.SetUpdateValue("total_number=?", req.TotalNumber)
		currDate.TotalNumber = req.TotalNumber
	}
	if req.Title != "" {
		updaq.SetUpdateValue("title=?", req.Title)
		currDate.Title = req.Title
	}
	if req.SeckillStart != 0 {
		updaq.SetUpdateValue("seckill_start=?", req.SeckillStart)
		currDate.SeckillStart = req.SeckillStart
	}
	if req.SeckillEnd != 0 {
		updaq.SetUpdateValue("seckill_end=?", req.SeckillEnd)
		currDate.SeckillEnd = req.SeckillEnd
	}
	if req.ShareUrl != "" {
		updaq.SetUpdateValue("share_url=?", req.ShareUrl)
		currDate.ShareUrl = req.ShareUrl
	}
	if req.ShareLogo != "" {
		updaq.SetUpdateValue("share_logo=?", req.ShareLogo)
		currDate.ShareLogo = req.ShareLogo
	}
	if req.ShareTitle != "" {
		updaq.SetUpdateValue("share_title=?", req.ShareTitle)
		currDate.ShareTitle = req.ShareTitle
	}
	if req.ShareContent != "" {
		updaq.SetUpdateValue("share_content=?", req.ShareContent)
		currDate.ShareContent = req.ShareContent
	}

	if req.BackgroundPicture != "" {
		if req.BackgroundPicture == "null" {
			req.BackgroundPicture = ""
		}
		updaq.SetUpdateValue("background_picture=?", req.BackgroundPicture)
		currDate.BackgroundPicture = req.BackgroundPicture
	}
	if req.BackgroundColor != "" {
		if req.BackgroundColor == "null" {
			req.BackgroundColor = ""
		}
		updaq.SetUpdateValue("background_color=?", req.BackgroundColor)
		currDate.BackgroundColor = req.BackgroundColor
	}
	if req.Routers != "" {
		updaq.SetUpdateValue("routers=?", req.Routers)
		currDate.Routers = req.Routers
	}
	if req.BuyRouters != "" {
		updaq.SetUpdateValue("buy_routers=?", req.BuyRouters)
		currDate.BuyRouters = req.BuyRouters
	}
	if req.StartTick != 0 {
		updaq.SetUpdateValue("starttick=?", req.StartTick)
		currDate.StartTick = req.StartTick
	}
	if req.EndTick != 0 {
		updaq.SetUpdateValue("endtick=?", req.EndTick)
		currDate.EndTick = req.EndTick
	}
	if req.Status != 0 {
		if req.Status != 1 && req.Status != -1 {
			req.Status = 1
		}
		updaq.SetUpdateValue("status=?", req.Status)
		currDate.Status = req.Status
	}

	updaq.SetUpdateValue("update_tick=?", nowTime)
	currDate.UpdateTick = nowTime

	updaq.PushCondition("id=?", req.Id)

	sql, values := updaq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	_, err := mysqlHelper.Exec(sql, values...)
	if err != nil {
		log.Errorf("update zjseckill fail ,~~~zjSeckillUpdate,err is %s", err.Error())
		return errorcode.EC_GL_INTERNAL_ERROR, errorcode.Msg(errorcode.EC_GL_INTERNAL_ERROR)
	}
	//更新缓存
	p.zjSeckillInfo[req.Id] = currDate

	//判断是否下架取消秒杀任务
	if currDate.Status == -1 {
		//取消所有任务
		GetZJSeckillUserService().CanclSeckillCallTask(currDate.Id, 1)
		GetZJSeckillUserService().CanclSeckillCallTask(currDate.Id, 2)
		GetZJSeckillUserService().CanclSeckillCallTask(currDate.Id, 3)
		log.Infof("下架~ 取消所有任务，id: %d", currDate.Id)
	}

	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS)
}

//web查询list
func (p *ZJSeckillInfoService) ZJSeckillInfoList(status int) []*ZJSeckillList {
	if status != 1 && status != -1 {
		status = 1
	}
	data := make([]*ZJSeckillList, 0)
	//遍历缓存取数据
	for _, value := range p.zjSeckillInfo {
		item := &ZJSeckillList{}
		if value.Status == status {
			item.Id = value.Id
			item.SeckillProductType = value.SeckillProductType
			item.SeckillProductId = value.SeckillProductId
			item.SeckillProductSid = value.SeckillProductSid
			item.ClickAble = value.ClickAble
			item.BackgroundPicture = value.BackgroundPicture
			item.BackgroundColor = value.BackgroundColor
			item.RegionCode = value.RegionCode
			item.Routers = value.Routers
			item.BuyRouters = value.BuyRouters
			item.Status = value.Status
			item.PicUrl = value.PicUrl
			item.Title = value.Title
			item.Price = value.Price
			item.OriginalPrice = value.OriginalPrice
			item.SellNumber = value.SellNumber
			item.TotalNumber = value.TotalNumber
			item.SeckillStart = time.Unix(value.SeckillStart, 0).Format("2006-01-02 15:04:05")
			item.SeckillEnd = time.Unix(value.SeckillEnd, 0).Format("2006-01-02 15:04:05")
			item.ShareUrl = value.ShareUrl
			item.ShareLogo = value.ShareLogo
			item.ShareTitle = value.ShareTitle
			item.ShareContent = value.ShareContent
			item.InsertTime = time.Unix(value.InsertTick, 0).Format("2006-01-02 15:04:05")
			item.UpdateTime = time.Unix(value.UpdateTick, 0).Format("2006-01-02 15:04:05")
			item.StartTick = time.Unix(value.StartTick, 0).Format("2006-01-02 15:04:05")
			item.EndTick = time.Unix(value.EndTick, 0).Format("2006-01-02 15:04:05")

			data = append(data, item)
		}
	}
	return data
}

//客户端查询数据
func (p *ZJSeckillInfoService) UserGetZJSeckillList(ids []int, regionCode string) []*ZJSeckillUserList {
	data := make([]*ZJSeckillUserList, 0)
	//遍历找到满足id的数据
	nowtick := time.Now().Unix()
	for _, dt := range ids {
		for key, value := range p.zjSeckillInfo {
			if key == dt {
				//当id满足，再过滤掉不在有效期的数据
				if value.StartTick <= nowtick && value.EndTick >= nowtick && value.Status == 1 &&
					IsRegionCode(value.RegionCode, regionCode) {
					item := &ZJSeckillUserList{}
					item.Id = value.Id
					item.ClickAble = value.ClickAble
					item.BackgroundPicture = value.BackgroundPicture
					item.BackgroundColor = value.BackgroundColor
					item.Routers = value.Routers
					item.BuyRouters = value.BuyRouters
					item.PicUrl = value.PicUrl
					item.Title = value.Title
					item.Price = value.Price
					item.OriginalPrice = value.OriginalPrice
					item.SellNumber = value.SellNumber
					item.TotalNumber = value.TotalNumber
					item.SeckillStart = value.SeckillStart
					item.SeckillEnd = value.SeckillEnd
					item.Share = &ShareItem{
						Url:     value.ShareUrl,
						Logo:    value.ShareLogo,
						Title:   value.ShareTitle,
						Content: value.ShareContent,
					}
					data = append(data, item)
				}
			}
		}
	}
	return data

}

//查询商品是否是秒杀,是秒杀，返回相应的基本信息
func (p *ZJSeckillInfoService) QuerySeckillData(productType, regionCode string, productId int) []*VerifySeckillResp {
	data := make([]*VerifySeckillResp, 0)
	if len(regionCode) < 4 && len(regionCode) > 0 {
		log.Warnf("regionCode不合法,regionCode: %s", regionCode)
		return data
	}
	// if len(regionCode) >= 4 {
	// 	regionCode = regionCode[:4]
	// }

	// data := &VerifySeckillResp{}
	for _, value := range p.zjSeckillInfo {
		nowTick := time.Now().Unix()
		if value.SeckillProductType == productType && value.SeckillProductId == productId &&
			value.Status == 1 && IsRegionCode(value.RegionCode, regionCode) &&
			nowTick >= value.StartTick && nowTick <= value.EndTick {
			item := &VerifySeckillResp{}
			item.SeckillProductSid = value.SeckillProductSid
			item.OriginalPrice = value.OriginalPrice
			item.Price = value.Price
			item.SeckillStartTick = value.SeckillStart
			item.SeckillEndTick = value.SeckillEnd
			//根据客户端的统一，这块将totalNum在返回层理解为库存
			item.TotalNum = value.TotalNumber - value.SellNumber
			item.SellNum = value.SellNumber

			data = append(data, item)
		}
	}
	return data
}

//下单印证秒杀
func (p *ZJSeckillInfoService) VerifySeckillData(productType, regionCode string, productSid int64, productId, price, buyNum int) (uint, string, int) {
	nowTick := time.Now().Unix()
	for _, value := range p.zjSeckillInfo {
		if value.SeckillProductType == productType && value.SeckillProductId == productId &&
			value.SeckillProductSid == productSid && value.Status == 1 && IsRegionCode(value.RegionCode, regionCode) {
			if nowTick >= value.SeckillStart && nowTick <= value.SeckillEnd {
				if value.Price == price {
					//秒杀条件满足，商品数目增加
					code, msg := p.SeckillSellNumChange(value.Id, buyNum)
					if code != 0 {
						return code, msg, 0
					}
					//如果数目为0了,通知结束
					log.Infof("减少商品数目，总数:%d,购买:%d,已售:%d", value.TotalNumber, buyNum, value.SellNumber)
					if value.TotalNumber-value.SellNumber == 0 {
						p.callSeckillEnd(productSid, productId, price)
					}
					return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS), value.Id
				} else {
					return 108, fmt.Sprintf("印证不通过!传入价格:%d,实际价格:%d", price, value.Price), 0
				}
			}
		}
	}
	return 107, "无记录", 0
}

//提前通知秒杀结束
func (p *ZJSeckillInfoService) callSeckillEnd(productSid int64, productId, price int) bool {
	daq := datatable.NewDataTableQuery()
	daq.SetTableName("seckill_call_task")
	daq.PushField(&datatable.FiledItem{Alias: "seckill_id", Field: "seckill_id"})
	daq.PushField(&datatable.FiledItem{Alias: "seckill_price", Field: "seckill_price"})
	daq.PushField(&datatable.FiledItem{Alias: "region_code", Field: "region_code"})
	daq.PushCondition("status = ?", 1)
	daq.PushCondition("call_status = ?", 3)
	daq.PushCondition("seckill_product_id = ?", productId)
	daq.PushCondition("seckill_product_sid = ?", productSid)
	sql, values := daq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	results, err := mysqlHelper.Query(sql, values...)
	if err != nil {
		log.Errorf("提前通知秒杀结束失败~,err is %s", err.Error())
		return false
	}
	if len(results) > 0 {
		regionCode := mysqlHelper.GetColString(results[0], "region_code")
		regionCodes := make([]string, 0)
		if regionCode != "" {
			regionCodes = strings.Split(regionCode, ",")
		}
		resp := zjservice.SyncSeckillMsg(productId, productSid, 3, price, regionCodes)
		if resp == nil {
			log.Warnf("同步秒杀信息请求失败")
		}
		if resp.Code != 0 {
			log.Warnf("同步秒杀信息失败,code:%d ,msg: %s", resp.Code, resp.Msg)
		}
		log.Infof("秒杀数目为0同步秒杀成功，serviceId: %d,sdId: %d,callStatus: %d,regionCode: %v", productId, productSid, 3, regionCodes)
		//任务置为无效
		seckillId := mysqlHelper.GetColInt(results[0], "seckill_id")
		GetZJSeckillUserService().CanclSeckillCallTask(seckillId, 3)
		return true
	}
	return false
}

//秒杀商品销售数目增加或者减少
func (p *ZJSeckillInfoService) SeckillSellNumChange(goodsId, changNum int) (uint, string) {
	p.zjSeckillSellNumUpLock.Lock()
	defer p.zjSeckillSellNumUpLock.Unlock()

	//从缓存中查
	dt, ok := p.zjSeckillInfo[goodsId]
	if !ok {
		return 101, "该秒杀商品不存在！"
	}
	if changNum > 0 {
		if dt.SellNumber+changNum > dt.TotalNumber {
			return 102, "该商品秒杀数目不够啦~"
		}
	}

	//数据库数据改变
	updaq := datatable.NewDataTableUpdate()
	updaq.SetTableName("zjseckill")
	updaq.SetUpdateValue("sell_number=sell_number+?", changNum)
	updaq.SetUpdateValue("update_tick=?", time.Now().Unix())
	updaq.PushCondition("id=?", goodsId)
	sql, values := updaq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	_, err := mysqlHelper.Exec(sql, values...)
	if err != nil {
		log.Errorf("update seckill sell_num  fail ,~~~SeckillSellNumUp,err is %s", err.Error())
		return errorcode.EC_GL_INTERNAL_ERROR, errorcode.Msg(errorcode.EC_GL_INTERNAL_ERROR)
	}
	//更新缓存
	dt.SellNumber += changNum
	p.zjSeckillInfo[goodsId] = dt
	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS)
}

//获取实时商品信息
func (p *ZJSeckillInfoService) GetZJSeckillItemById(goodsId int) *ZJSeckillItem {
	dt, ok := p.zjSeckillInfo[goodsId]
	if !ok {
		return nil
	}
	return dt
}
